#include "streamingbufferedai.h"
#include <QMessageBox>
#include <QPalette>
#include <QWidget>
#include <qmath.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <dirent.h>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <cstdlib>
#include <ctime>
#include <typeinfo>
#include <string.h>
#include <curl/curl.h>
#include <unistd.h>
#include <string.h>
#include<iomanip>
#define adress "/var/db/Advantech/"

using namespace std;
using namespace Automation::BDaq;


extern AI_StreamingBufferedAi *ww;
using namespace std;

AI_StreamingBufferedAi::AI_StreamingBufferedAi(QDialog *parent, Qt::WindowFlags flags)
    : QDialog(parent, flags)
{
    ui.setupUi(this);
    //Set the minimum and close button of the main frame.
    this->setWindowFlags(Qt::WindowFlags(Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint));

    //Set the background image for the main frame.
    this->setAutoFillBackground(true);
    QPixmap pixMap(":/AI_StreamingBufferedAi/Resources/Background.png");
    QPalette backPalette;
    backPalette.setBrush(this->backgroundRole(), QBrush(pixMap));
    this->setPalette(backPalette);

    graph = new SimpleGraph(ui.graphFrame);
    graph->setFixedSize(ui.graphFrame->size());

    timeUnit = Millisecond;
    rawDataBufferLength = 0;
    scaledData = NULL;
    //AI_StreamingBufferedAi A,B;
    waveformAiCtrl  = WaveformAiCtrl::Create();

    waveformAiCtrl->addDataReadyHandler(OnDataReadyEvent, this);
    waveformAiCtrl->addOverrunHandler(OnOverRunEvent, this);
    waveformAiCtrl->addCacheOverflowHandler(OnCacheOverflowEvent, this);
    waveformAiCtrl->addStoppedHandler(OnStoppedEvent, this);
    //

    connect(ui.btnConfigure, SIGNAL(clicked()), this, SLOT(ButtonConfigureClicked()));
    connect(ui.btnStart, SIGNAL(clicked()),this,SLOT(ButtonStartClicked()));
    connect(ui.btnPause, SIGNAL(clicked()), this, SLOT(ButtonPauseClicked()));
    connect(ui.btnStop, SIGNAL(clicked()), this, SLOT(ButtonStopClicked()));
    connect(ui.sldDiv, SIGNAL(valueChanged(int)), this, SLOT(DivValueChanged(int)));
    //emit void AmySignal();

    ui.tableWidget->setColumnCount(3);
    QStringList header;
    header<<"空化"<<"烈度"<<"时间";
    ui.tableWidget->setHorizontalHeaderLabels(header);
    ui.tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    ui.tableWidget->setColumnWidth(0,10);
    ui.tableWidget->setColumnWidth(1,30);
    ui.tableWidget->setColumnWidth(2,140);
    ui.tableWidget->horizontalHeader()->setSectionResizeMode(0,QHeaderView::Stretch);
    ui.tableWidget->setAlternatingRowColors(1);
    ui.tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui.tableWidget->verticalHeader()->setVisible(false);
    ui.tableWidget->setShowGrid(false);
    ui.progressBar->setMaximum(200);//

    ui.pushButton->resize(50,50);
    ui.pushButton->setStyleSheet("background-color: rgb(0, 0, 0);"
                                 "border-radius: 25px;  border: 2px groove gray;"
                                 "border-style: outset;");
    ui.pushButton_2->resize(50,50);
    ui.pushButton_2->setStyleSheet("background-color: rgb(0, 0, 0);"
                                 "border-radius: 25px;  border: 2px groove gray;"
                                 "border-style: outset;");
    ui.pushButton_3->resize(50,50);
    ui.pushButton_3->setStyleSheet("background-color: rgb(0, 0, 0);"
                                 "border-radius: 25px;  border: 2px groove gray;"
                                 "border-style: outset;");


          connect(a, SIGNAL(valueChanged(QString)), b, SLOT(update(QString)));


    }
AI_StreamingBufferedAi::~AI_StreamingBufferedAi()
{
   if (waveformAiCtrl != NULL)
   {
      waveformAiCtrl->Dispose();
      waveformAiCtrl = NULL;
   }

    if (scaledData != NULL)
    {
        delete []scaledData;
        scaledData = NULL;
    }
}

void AI_StreamingBufferedAi::Initialize()
{
    setWindowTitle(tr("Streaming AI - Run(") + configure.deviceName + tr(")"));

    ConfigureDevice();
    ConfigureGraph();
//	InitializeList();

    ui.btnConfigure->setEnabled(true);
    ui.btnStart->setEnabled(true);
    ui.btnPause->setEnabled(false);
    ui.btnStop->setEnabled(false);
    ui.sldDiv->setEnabled(true);
}

void AI_StreamingBufferedAi::ConfigureDevice()
{
    ErrorCode errorCode = Success;
    if (scaledData != NULL)
    {
        delete []scaledData;
        scaledData = NULL;
    }

    rawDataBufferLength = configure.sectionLength * configure.channelCount;

    scaledData = new double[rawDataBufferLength];
    if (scaledData == NULL)
    {
        QMessageBox::information(this, tr("Warning Information"),
            tr("Sorry! Error in allocating memory...."));
        return;
    }

    // Select a device with AccessWrite/AccessWriteWithReset mode with device number
    // or device description.
    std::wstring description = configure.deviceName.toStdWString();
    DeviceInformation selected(description.c_str());

    errorCode = waveformAiCtrl->setSelectedDevice(selected);
    CheckError(errorCode);

    std::wstring profile = configure.profilePath.toStdWString();
    errorCode = waveformAiCtrl->LoadProfile(profile.c_str());
    CheckError(errorCode);

    //Set the streaming mode.
    errorCode = waveformAiCtrl->getConversion()->setChannelCount(configure.channelCount);
    CheckError(errorCode);
    errorCode = waveformAiCtrl->getConversion()->setChannelStart(configure.channelStart);
    CheckError(errorCode);
    errorCode = waveformAiCtrl->getConversion()->setClockRate(configure.clockRatePerChan);
    CheckError(errorCode);
    errorCode = waveformAiCtrl->getRecord()->setSectionLength(configure.sectionLength);
    CheckError(errorCode);
    errorCode = waveformAiCtrl->getRecord()->setSectionCount(sectionCount);//The 0 means setting 'streaming' mode.
    CheckError(errorCode);

   for (int i = 0; i < waveformAiCtrl->getChannels()->getCount(); i++)
    {
        errorCode = waveformAiCtrl->getChannels()->getItem(i).setValueRange(configure.valueRange);
        CheckError(errorCode);
    }

    errorCode = waveformAiCtrl->Prepare();
    CheckError(errorCode);
}

void AI_StreamingBufferedAi::ConfigureGraph()
{
   double clockRate = waveformAiCtrl->getConversion()->getClockRate();
   int tUnit = (int)Millisecond;
   double timeInterval = 100.0 * graph->rect().width() / clockRate;
   while (clockRate >= 10 * 1000)
   {
       timeInterval *= 1000;
       clockRate /= 1000;
       --tUnit;
   }
   timeUnit = (TimeUnit)tUnit;

   int divValue = (int)timeInterval;
   ui.sldDiv->setMaximum(4 * divValue);
   int divMin = divValue / 10;
   if ( divMin == 0 )
   {
       divMin = 1;
   }
   ui.sldDiv->setMinimum(divMin);
   ui.sldDiv->setValue(divValue);
   SetXCord();

    ValueUnit unit;
    MathInterval rangeY;
    QString yRanges[3];
    ErrorCode errorCode = AdxGetValueRangeInformation(configure.valueRange, 0, NULL,
        &rangeY, &unit);
    CheckError(errorCode);

    graph->GetYCordRange(yRanges, rangeY.Max, rangeY.Min, unit);
    ui.lblYCoordinateMax->setText(yRanges[0]);
    ui.lblYCoordinateMin->setText(yRanges[1]);
    ui.lblYCoordinateMid->setText(yRanges[2]);

    graph->m_yCordRangeMax = rangeY.Max;
    graph->m_yCordRangeMin = rangeY.Min;
    graph->Clear();
}

/*void AI_StreamingBufferedAi::InitializeList()
{
    ui.listWidget->clear();
    QListWidgetItem *item = NULL;
    for (int i = 0; i < configure.channelCount; i++)
    {
        item = new QListWidgetItem(tr(""), ui.listWidget);
        item->setBackgroundColor(SimpleGraph::lineColor[i]);
        item->setSizeHint(QSize(54, 21));
    }
}*/

void AI_StreamingBufferedAi::CheckError(ErrorCode errorCode)
{
    if (BioFailed(errorCode))
    {
        QString message = tr("Sorry, there are some errors occurred, Error Code: 0x") +
            QString::number(errorCode, 16).right(8).toUpper();
        QMessageBox::information(this, "Warning Information", message);
    }
}

void AI_StreamingBufferedAi::SetXCord()
{
    graph->m_xCordTimeDiv = (double)ui.sldDiv->value();
    QString xRanges[2];

    double shiftMaxValue = qRound(graph->m_xCordTimeDiv * 10 + graph->m_xCordTimeOffset);
    graph->GetXCordRange(xRanges, shiftMaxValue, graph->m_xCordTimeOffset, timeUnit);
    ui.lblXCoordinateStart->setText(xRanges[1]);
    ui.lblXCoordinateEnd->setText(xRanges[0]);
}

void AI_StreamingBufferedAi::DivValueChanged(int value)
{
    graph->Div(value);
    SetXCord();

}

void AI_StreamingBufferedAi::ButtonConfigureClicked()
{
    configureDialog->RefreshConfigureParameter();
    int resultDialog = configureDialog->exec();
    if (resultDialog == QDialog::Accepted)
    {
        configure = configureDialog->GetConfigureParameter();
        Initialize();

    }
}
void AI_StreamingBufferedAi::start()
{
    ui.btnConfigure->setEnabled(false);
    ui.btnStart->setEnabled(false);
    ui.btnPause->setEnabled(true);
    ui.btnStop->setEnabled(true);

    ww->waveformAiCtrl->Start();
    xInc = 1.0 / waveformAiCtrl->getConversion()->getClockRate();
}

void AI_StreamingBufferedAi::ButtonStartClicked()
{
    ui.btnConfigure->setEnabled(false);
    ui.btnStart->setEnabled(false);
    ui.btnPause->setEnabled(true);
    ui.btnStop->setEnabled(true);

    ErrorCode errorCode = waveformAiCtrl->Start();
    CheckError(errorCode);
    xInc = 1.0 / waveformAiCtrl->getConversion()->getClockRate();

}

void AI_StreamingBufferedAi::ButtonPauseClicked()
{
    ErrorCode errorCode = waveformAiCtrl->Stop();
    CheckError(errorCode);

    ui.btnStart->setEnabled(true);
    ui.btnPause->setEnabled(false);
    ui.btnStop->setEnabled(true);
}

void AI_StreamingBufferedAi::ButtonStopClicked()
{
    ErrorCode errorCode = waveformAiCtrl->Stop();
    CheckError(errorCode);

    graph->Clear();

    ui.btnConfigure->setEnabled(true);
    ui.btnStart->setEnabled(true);
    ui.btnPause->setEnabled(false);
    ui.btnStop->setEnabled(false);
}
static string gen_file_name()
{

    time_t currentTime=time(NULL);
    char chCurrentTime[256];
    strftime(chCurrentTime,sizeof(chCurrentTime),"%Y:%m:%d-%H:%M:%S",localtime(&currentTime));
    string stCurrentTime=chCurrentTime;
    string fname=stCurrentTime;

    return fname ;
}

void write_data(ofstream outfile, double *scaledData, int len)
{

    for(int i = 0; i<len; ++i )
        outfile << scaledData[i] << std::endl;
}
static size_t get_data(void *ptr, size_t size, size_t nmemb, void *buf)  //这个函数是为了符合CURLOPT_WRITEFUNCTION, 而构造的
{
    memcpy(buf,ptr,(size_t) size*nmemb);
    return size*nmemb;
}

static int cpost(char*p, string *value)
{
    CURL *curl;
       CURLcode res;
       char buf[32];
       curl = curl_easy_init();
       if(curl) {
         curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
         ifstream in;
         in.open("param.txt");
         char data[1024];
         in.getline(data, 1024);
         string w=data;
         char fs[20];
         strcpy(fs,w.c_str());
         memset(data,0,1024);
         in.getline(data, 1024);
         memset(data,0,1024);
         in.getline(data, 1024);
         char name[50];
         strcpy(name, data);
         char ip_adress[45]="/SoundAnalysis";
         strcat(name,ip_adress );
         in.close();
         curl_easy_setopt(curl, CURLOPT_URL,name);
         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl,CURLOPT_VERBOSE,1); //打印调试信息
       curl_easy_setopt(curl,CURLOPT_HEADER,1); //将响应头信息和相应体一起传给write_data
         curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "http");
         struct curl_slist *headers = NULL;
         headers = curl_slist_append(headers, "Content-Type: multipart/form-data");
         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
         curl_mime *mime;
         curl_mimepart *part;
         mime = curl_mime_init(curl);
         part = curl_mime_addpart(mime);
         curl_mime_name(part, "fs");
         curl_mime_data(part, fs, CURL_ZERO_TERMINATED);
         part = curl_mime_addpart(mime);
         curl_mime_name(part, "fsTopPoint");
         curl_mime_data(part, "3500", CURL_ZERO_TERMINATED);
         part = curl_mime_addpart(mime);
         curl_mime_name(part, "data");
         char ads[25] = adress;
         char final[45];
         strcpy(final, ads);
         strcat(final, p);
         curl_mime_filedata(part,final);
         curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
         curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,get_data);
         curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
         res = curl_easy_perform(curl);
         curl_mime_free(mime);
       }
       curl_easy_cleanup(curl);
       *value = buf;

           return res;
}
FileNamer*AI_StreamingBufferedAi::a = new FileNamer();
DisplayAgent* AI_StreamingBufferedAi::b = new DisplayAgent();

static int test(string name)
{
     AI_StreamingBufferedAi::a->setValue(QString::fromStdString(name));     //  a.value() == 1
     return 0;
}
void AI_StreamingBufferedAi::OnDataReadyEvent(void * sender, BfdAiEventArgs * args, void * userParam)
{

    AI_StreamingBufferedAi * uParam = (AI_StreamingBufferedAi *)userParam;
    int32 remainingCount = args->Count;
    int32 getDataCount = 0, returnedCount = 0;
    int32 bufSize = uParam->configure.sectionLength * uParam->configure.channelCount;

    string fname = gen_file_name();
    string asd=adress+fname;
    ofstream outfile(asd.c_str(),ios::app);
    do{
        getDataCount = qMin(bufSize,  remainingCount);
        ErrorCode ret = ((WaveformAiCtrl*)sender)->GetData(getDataCount, uParam->scaledData, 0, &returnedCount, NULL, NULL, NULL);
        remainingCount -= returnedCount;   //refresh scaledData
        if (ret != Success && ret != WarningRecordEnd)
        {
            QString message = tr("Sorry, there are some errors occurred, Error Code: 0x") +
                QString::number(ret, 16).right(8);
            QMessageBox::information(uParam, "Warning Information", message);
            return;
        }

        // Write part of returned data
        for(int i = 0; i<returnedCount; ++i )
            outfile << uParam->scaledData[i] << std::endl;

       uParam->graph->Chart(uParam->scaledData, uParam->configure.channelCount, returnedCount / uParam->configure.channelCount, uParam->xInc);
   } while(remainingCount > 0);
   ww->waveformAiCtrl->Stop();//stop collecting and wait for cpost return
   outfile.close();
   test(fname);
}
void DisplayAgent::update(QString fname)
{
        string value;
        string a=fname.toStdString();
        //std::cout << "<Display> [Signal received] New value: " << a << std::endl;
        const  char *name=a.c_str();//Convert and send to Cpost
        int ret = cpost((char*)name, &value);
        if(ret!=0){
            string x="-1";
             ww->TableWidget(QString::fromStdString(a), QString::fromStdString(x), QString::fromStdString(x));
             //send "-1" when unconnected;
        }else
            {
        string f=value.substr(0,1);//数据格式为“1，2.55"，分割0位和2到5位分别发送给表格；
        string t=value.substr(2,5);
        ww->TableWidget(QString::fromStdString(a), QString::fromStdString(f), QString::fromStdString(t));
        }

}
void FileNamer::setValue(QString value)
{
    if (value != m_value) {
        m_value = value;

        emit valueChanged(value);

    }

}
void AI_StreamingBufferedAi::TableWidget(QString fname, QString a,QString ret)
{
    string s = fname.toStdString();//connect strings
    string q = a.toStdString();
    string x="_"+q;
    char fs[100];
    strcpy(fs,s.c_str());
    char fg[100];
    strcpy(fg,x.c_str());
    char z[100]=adress;
    strcat(z,fs);
    char b[100]=adress;
    strcat(b,fs);
    strcat(z,fg);
    char cmd[200];
    sprintf(cmd, "mv %s %s" ,b,z );//add res of the konghua in the end
    system(cmd);
    string time=s.substr(5,14);
    QString time1 = QString::fromStdString(time);
           ui.tableWidget->setRowCount(20);
           int rowCount = ui.tableWidget->rowCount();
           rowCount-=20;
           ui.tableWidget->insertRow(rowCount);
           ui.tableWidget->setItem(rowCount,0,new QTableWidgetItem(a));
           ui.tableWidget->setItem(rowCount,1,new QTableWidgetItem(ret));
           ui.tableWidget->setItem(rowCount,2,new QTableWidgetItem(time1));
           ui.tableWidget->item(rowCount,0)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
           ui.tableWidget->item(rowCount,1)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
           ui.tableWidget->item(rowCount,2)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
           bool ok;
           float ret1 = QString(ret).toFloat(&ok);
           if (ret1<=90)
           {
           ui.pushButton->setStyleSheet("background-color: rgb(0, 0, 0);"
                                        "border-radius: 25px;  border: 2px groove gray;"
                                        "border-style: outset;");
           ui.pushButton_2->setStyleSheet("background-color: rgb(0, 0, 0);"
                                        "border-radius: 25px;  border: 2px groove gray;"
                                        "border-style: outset;");
           ui.pushButton_3->setStyleSheet("background-color: rgb(0, 255, 0);"
                                        "border-radius: 25px;  border: 2px groove gray;"
                                        "border-style: outset;");
             ui.progressBar->setValue(ret1);
            }
        else if (90<ret1,ret1<=110)

            {
       ui.pushButton->setStyleSheet("background-color: rgb(0, 0, 0);"
                                    "border-radius: 25px;  border: 2px groove gray;"
                                    "border-style: outset;");
       ui.pushButton_2->setStyleSheet("background-color: rgb(255, 255, 0);"
                                    "border-radius: 25px;  border: 2px groove gray;"
                                    "border-style: outset;");
       ui.pushButton_3->setStyleSheet("background-color: rgb(0, 0, 0);"
                                    "border-radius: 25px;  border: 2px groove gray;"
                                    "border-style: outset;");
       ui.progressBar->setValue(ret1);
            }
        else if (ret1>110)
            {
       ui.pushButton->setStyleSheet("background-color: rgb(255, 0, 0);"
                                    "border-radius: 25px;  border: 2px groove gray;"
                                    "border-style: outset;");
       ui.pushButton_2->setStyleSheet("background-color: rgb(0, 0, 0);"
                                    "border-radius: 25px;  border: 2px groove gray;"
                                    "border-style: outset;");
       ui.pushButton_3->setStyleSheet("background-color: rgb(0, 0, 0);"
                                    "border-radius: 25px;  border: 2px groove gray;"
                                    "border-style: outset;");
        ui.progressBar->setValue(ret1);
             }
         waveformAiCtrl->Start();//restart collecting
}



void AI_StreamingBufferedAi::OnOverRunEvent(void * sender, BfdAiEventArgs * args, void * userParam)
{
   /*
   AI_StreamingBufferedAi * uParam = (AI_StreamingBufferedAi *)userParam;
   QString message = tr("The event over run has happened!");
   QMessageBox::information(uParam, "Warning Information", message);
   */

}
void AI_StreamingBufferedAi::OnCacheOverflowEvent(void * sender, BfdAiEventArgs * args, void * userParam)
{
   /*
   AI_StreamingBufferedAi * uParam = (AI_StreamingBufferedAi *)userParam;
   QString message = tr("The event cache over flow has happened!");
   QMessageBox::information(uParam, "Warning Information", message);
   */
}

void AI_StreamingBufferedAi::OnStoppedEvent(void * sender, BfdAiEventArgs * args, void * userParam)
{
   /*
   AI_StreamingBufferedAi * uParam = (AI_StreamingBufferedAi *)userParam;
   QString message = tr("The event stopped has happened!");
   QMessageBox::information(uParam, "Warning Information", message);
   */
}
